﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using SpeechLib;


namespace JustTypeUI
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
    /// 
    /// Main Author: Han Yu
	/// </summary>
	public partial class MainWindow : Window
	{ 
        Logic.Control control;
        private System.Timers.Timer tmrClock;
        private System.Windows.Forms.NotifyIcon notifier = new System.Windows.Forms.NotifyIcon();
        //List<TextBlock> tb = new List<TextBlock>();
        static BackgroundWorker bw;
        int count=0;
        Boolean quiet=true;
		public MainWindow()
		{
			this.InitializeComponent();
            Initialize();
		}

        private void InitializeBackgroundWorker()
        {
            bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(speak);
            if (!bw.IsBusy && quiet) bw.RunWorkerAsync("welcome to just type");
        }

        private void hotkey_HotKeyPressed(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Minimized)
            {
                Show();
                this.WindowState = WindowState.Normal;
                this.Activate();
                this.notifier.Visible = false;
                if (!bw.IsBusy && quiet) bw.RunWorkerAsync("Glad to see you again!");
            }

            else if (this.WindowState == WindowState.Normal)
            {
                Hide();
                this.WindowState = WindowState.Minimized;
                this.notifier.Visible = true;
                this.notifier.ShowBalloonTip(4000);
                if (!bw.IsBusy && quiet) bw.RunWorkerAsync(this.notifier.BalloonTipText);
            }
        }

        private void Initialize()
        {
            InitializeControl();
            InitializeBackgroundWorker();
            InitializeNotifier();
            InitializeTmrClock();
            InitializeTextBlocks();

            tasksListBox.DataContext = control.ResultList.ResultTasks;
            System.Windows.Data.Binding binding = new System.Windows.Data.Binding("FeedbackMessage");
            binding.Source = control.FeedbackValue;
            statusbar.SetBinding(TextBlock.TextProperty, binding);

            control.Refresh();
        }

        private void InitializeTextBlocks()
        {
            Textbox.Text = "";
            //setTextblk();
            this.textBlock2.Text = "";
            this.textBlock2.Text = DateTime.Now.ToString("MMM dd ddd");
            Textbox.Focus();
        }

        private void InitializeControl()
        {
            control = Logic.Control.GetInstance();
            Debug.Assert(control != null);
        }

        private void InitializeTmrClock()
        {
            tmrClock = new System.Timers.Timer(1000.0);
            tmrClock.Elapsed += new System.Timers.ElapsedEventHandler(tmrClock_Elapsed);
            tmrClock.Enabled = true;
            SetTimeResouce();
        }

        private void InitializeNotifier()
        {
            this.notifier.Text = "JType To-Do Manager -- your humble assistant!";
            this.notifier.Visible = false;
            this.notifier.Icon = Properties.Resources.icon;
            this.notifier.BalloonTipTitle = "Dear User:";
            this.notifier.BalloonTipText = "I will be waiting here! Pleased to serve you!";
            this.notifier.DoubleClick += new EventHandler(notifier_Click);
            this.notifier.Visible = false;
        }

        private void notifier_Click(object sender, EventArgs e)
        {
            Show();
            this.WindowState = WindowState.Normal;
            this.Activate();
            this.notifier.Visible = false;
            if (!bw.IsBusy && quiet) bw.RunWorkerAsync("Glad to see you again!");
        }

        private void tmrClock_Elapsed(Object sender, System.Timers.ElapsedEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(SetTimeResouce));
            if (count == 59)
            {
                count = 0;
                remind();
                
            }
            else
                count++;

        }
        private void remind()
        {
            List<Task> list = control.TaskList;
            for (int i = 0; i < list.Count; i++)
            {
                TimeSpan ts;
                ts = list[i].Deadline - DateTime.Now;
                if ( ts.Minutes < 1 && ts.Minutes >= 0)
                {
                    if (!bw.IsBusy) bw.RunWorkerAsync(list[i].Name);
                }
            }
        }
        private void SetTimeResouce()
        {
            this.Resources.Remove("TimeNow");
            this.Resources.Add("TimeNow", DateTime.Now.ToString("T"));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string messageText = "To add a teask:\n \"add [task name] at [location] before [deadline]\" \n To delete a task:\n \"delete [task index] / [task keyword (name, date, location and etc.)]\" \n To search a task:\n \"search [task keyword]\" \n To edit a task:\n \"edit [task index] at [location] before [deadline]\" \n For other information, please refer to the user manual!";
            string messageBoxTitle = "Quick help";
            MessageBoxButton button = MessageBoxButton.OK;
            MessageBoxImage icon = MessageBoxImage.Question;
            MessageBox.Show(messageText,messageBoxTitle,button,icon);
        }

        private void Textbox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key==Key.Enter)
            {
                if (Textbox.Text != "")
                {
                    this.statusLabel.Content = "Upcoming";
                    control.Process(Textbox.Text);
                }
                Textbox.Text = "";
                if (!bw.IsBusy && quiet) bw.RunWorkerAsync(control.FeedbackValue.FeedbackMessage);
            };
        }


        private void LayoutRoot_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.D && (Keyboard.Modifiers == ModifierKeys.Control))
            {
                control.Refresh();
                this.statusLabel.Content = "Upcoming";
            }
            else if (e.Key == Key.Q && (Keyboard.Modifiers == ModifierKeys.Control))
            {
                this.Close();
            }
            else if (e.Key == Key.H && (Keyboard.Modifiers == ModifierKeys.Control))
            {
                control.ShowCompleted();
                this.statusLabel.Content = "Completed";
            }
            else if (e.Key == Key.U && (Keyboard.Modifiers == ModifierKeys.Control))
            {
                control.Process("undo");
                if (!bw.IsBusy && quiet) bw.RunWorkerAsync(control.FeedbackValue.FeedbackMessage);
            }
            else if (e.Key == Key.R && (Keyboard.Modifiers == ModifierKeys.Control))
            {
                control.Process("redo");
                if (!bw.IsBusy && quiet) bw.RunWorkerAsync(control.FeedbackValue.FeedbackMessage);
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            control.WriteFile();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            setHotkey();
        }
        

        private void setHotkey()
        {
            HotKey hotkey = new HotKey(HwndSource.FromVisual(App.Current.MainWindow as Visual) as HwndSource);
            hotkey.Modifiers = HotKey.ModifierKeys.Control;
            hotkey.Key = System.Windows.Input.Key.A;
            hotkey.HotKeyPressed += hotkey_HotKeyPressed;
            hotkey.Enabled = true;
        }

        private void speak(object sender, DoWorkEventArgs e)
        {
            String text = (String)e.Argument;
            SpVoice spk = new SpVoice();
            spk.Volume = 100;
            if(text != null)
                spk.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
        }

        public class HotKeyEventArgs : EventArgs
        {
            public HotKey Hotkey { get; private set; }

            public HotKeyEventArgs(HotKey hotkey)
            {
                Hotkey = hotkey;
            }
        }

        public class HotKey
        {
            private const int WM_HOTKEY = 786;

            [DllImport("user32", CharSet = CharSet.Ansi,
                       SetLastError = true, ExactSpelling = true)]
            private static extern int RegisterHotKey(IntPtr hwnd,
                    int id, int modifiers, int key);

            [DllImport("user32", CharSet = CharSet.Ansi,
                       SetLastError = true, ExactSpelling = true)]
            private static extern int UnregisterHotKey(IntPtr hwnd, int id);

            public enum ModifierKeys : int
            {
                Alt = 1,
                Control = 2,
                Shift = 4,
                Win = 8
            }

            public Key Key { get; set; }
            public ModifierKeys Modifiers { get; set; }

            public event EventHandler<HotKeyEventArgs> HotKeyPressed;

            private int id;

            private HwndSourceHook hook;
            private HwndSource hwndSource;

            public HotKey(HwndSource hwndSource)
            {
                this.hook = new HwndSourceHook(WndProc);
                this.hwndSource = hwndSource;
                hwndSource.AddHook(hook);

                Random rand = new Random((int)DateTime.Now.Ticks);
                id = rand.Next();
            }

            private bool enabled;
            public bool Enabled
            {
                get
                {
                    return enabled;
                }
                set
                {
                    if (value != enabled)
                    {
                        if ((int)hwndSource.Handle != 0)
                        {
                            if (value)
                                RegisterHotKey(hwndSource.Handle, id, (int)Modifiers, KeyInterop.VirtualKeyFromKey(Key));
                            else
                                UnregisterHotKey(hwndSource.Handle, id);
                            int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                            if (error != 0)
                                throw new System.ComponentModel.Win32Exception(error);
                        }

                        enabled = value;
                    }
                }
            }

            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam,
                    IntPtr lParam, ref bool handled)
            {
                if (msg == WM_HOTKEY)
                {
                    if ((int)wParam == id)
                        if (HotKeyPressed != null)
                            HotKeyPressed(this, new HotKeyEventArgs(this));
                }

                return new IntPtr(0);
            }

            private bool disposed;

            protected virtual void Dispose(bool disposing)
            {
                if (disposed)
                    return;

                if (disposing)
                {
                    hwndSource.RemoveHook(hook);
                }

                Enabled = false;

                disposed = true;
            }

            public void Dispose()
            {
                this.Dispose(true);
                GC.SuppressFinalize(this);
            }

            ~HotKey()
            {
                this.Dispose(false);
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (quiet)
            {
                quiet = false;
                quietbtn.Background = Brushes.White;
            }
            else
            {
                quiet = true;
                Brush brush = new SolidColorBrush(Color.FromRgb(19,17,78));
                quietbtn.Background = brush; ;
            }
        }
	}
}